package com.power.leopard.remote.provider.filter;

import java.util.List;

import com.power.leopard.constants.Constants;
import com.power.leopard.remote.ServiceMethod;
import com.power.leopard.remote.ServiceMethodFactory;
import com.power.leopard.remote.common.domain.InvocationRequest;
import com.power.leopard.remote.common.domain.InvocationResponse;
import com.power.leopard.remote.common.process.ServiceInvocationFilter;
import com.power.leopard.remote.common.process.ServiceInvocationHandler;
import com.power.leopard.remote.provider.domain.ProviderContext;
import com.power.leopard.remote.provider.domain.RequestAbortedException;
import com.power.leopard.remote.provider.process.ProviderProcessInterceptor;
import com.power.leopard.remote.provider.process.ProviderProcessInterceptorFactory;
import com.power.leopard.remote.provider.util.ProviderHelper;
import com.power.leopard.util.ContextUtils;
import com.power.leopard.util.ProviderUtils;
import com.power.leopard.util.TimelineManager;
import com.power.leopard.util.TimelineManager.Phase;

public class BusinessProcessFilter implements ServiceInvocationFilter<ProviderContext> {

	public InvocationResponse invoke(ServiceInvocationHandler handler, ProviderContext providerContext) throws Throwable {
		InvocationRequest request = providerContext.getRequest();
		if (request.getMessageType() == Constants.MESSAGE_TYPE_SERVICE) {
			if (Constants.RESET_TIMEOUT && request.getTimeout() > 0) {
				ContextUtils.putLocalContext(Constants.REQUEST_TIMEOUT, request.getTimeout());
			}
			if (Thread.currentThread().isInterrupted()) {
				StringBuilder msg = new StringBuilder();
				msg.append("the request has been canceled by timeout checking processor:").append(request);
				throw new RequestAbortedException(msg.toString());
			}

			List<ProviderProcessInterceptor> interceptors = ProviderProcessInterceptorFactory.getInterceptors();
			for (ProviderProcessInterceptor intercepter : interceptors) {
				intercepter.preInvoke(request);
			}

			InvocationResponse response = null;
			ServiceMethod serviceMethod = providerContext.getServiceMethod();
			if (serviceMethod == null) {
				serviceMethod = ServiceMethodFactory.getMethod(request);
			}
			if (Constants.REPLY_MANUAL && request.getCallType() == Constants.CALLTYPE_REPLY) {
				request.setCallType(Constants.CALLTYPE_NOREPLY);
				ProviderHelper.setContext(providerContext);
			}
			// TIMELINE_biz_start
			if (TimelineManager.isEnabled()) {
				TimelineManager.time(request, TimelineManager.getRemoteIp(), Phase.BusinessStart);
			}
			Object returnObj = serviceMethod.invoke(request.getParameters());
			if (TimelineManager.isEnabled()) {
				TimelineManager.time(request, TimelineManager.getRemoteIp(), Phase.BusinessEnd);
			}
			// TIMELINE_biz_end
			if (request.getCallType() == Constants.CALLTYPE_REPLY) {
				response = ProviderUtils.createSuccessResponse(request, returnObj);
			}
		}
		return null;
	}

}
